﻿#include "OPFInterface.h"
#include <direct.h>
#include <io.h>
#include <BaseCommon.h>
#include <BPAFilesIO.h>
#include "BPAInterface.h"
#include "OPF\PowerFlowAutoAdjustment.h"
#include "OPF\ToExecuteMinPf.h"
#include "OPF\MinPowerFlowRes.h"
#include "OPF\MinPowerBalanceInZone.h"

#define STS_SUCCEED  0
#define STS_FAILED  -1
using namespace JGG;
namespace BPA{
	namespace OPF
	{
		class OPF_Analysis
		{
			
		public:
            OPF_Analysis(const char* database, int caseid)
            {
                this->database = database;
                this->caseid = caseid;
            }

            const char* database;
			int caseid;

			void CreateTempDir()
			{
				const char* outdat = "./bpa_temp/OPF_temp.dat";
				//从数据库中回写速度较慢
				BPAFileWriteBack(database, outdat, caseid);
				//copy pfnt.exe
				const string origpfnt = "./pfnt.exe";
				const string newpfnt = "./bpa_temp/pfnt.exe";
				const string origOPF = "./Powerflow.exe";
				const string newOPF = "./bpa_temp/Powerflow.exe";
				const string origcfg = "general.cfg";
				const string newcfg = "./bpa_temp/general.cfg";
				if (filesystem::CFile::exists(origpfnt))
				{
					filesystem::CFile::copy(origpfnt, newpfnt);
				}
				else
				{
					//$trace_p("缺少pfnt.exe!");
				}
				if (filesystem::CFile::exists(origOPF))
				{
					filesystem::CFile::copy(origOPF, newOPF);
				}
				else
				{
					//$trace_p("缺少Powerflow.exe!");
				}
				if (filesystem::CFile::exists(origcfg))
				{
					filesystem::CFile::copy(origcfg, newcfg);
				}
				else
				{
					//$trace_p("缺少Powerflow.exe!");
				}

			}
			void ExecutePF(string OpenFileName)
			{
				//$trace_p("开始BPA潮流计算");
				string pfntexe = "./bpa_temp/pfnt.exe";
				string DatPathTemp;
				DatPathTemp= "./bpa_temp/"+OpenFileName;
				//cout << "计算：" << DatPathTemp << endl;
				string datpath = "\"" + DatPathTemp + "\"";
				std::string command = pfntexe + " " + datpath;
				JGG::Process processpfnt(command);
				int exit_status = processpfnt.get_exit_status();
				//cout << exit_status;
			}
		};
	}
}

namespace BPA{
    BPA_OPF_Analysis::BPA_OPF_Analysis(const char* Database,
		int CaseID) :impl(0)
	{
        impl = new OPF::OPF_Analysis(Database, CaseID);
		impl->database = Database;
		impl->caseid = CaseID;
	}
	BPA_OPF_Analysis::~BPA_OPF_Analysis()
	{
		
	}
	int BPA_OPF_Analysis::BPA_OPF_Parse(
		BPA::BPAFilesIO::ZoneInfoVector& zone,
		BPA::BPAFilesIO::LineResultVector& line,
		BPA::BPAFilesIO::BusResultVector& bus,
		BPA::BPAFilesIO::TranResultVector& trans)
	{
		impl->CreateTempDir();
		impl->ExecutePF("OPF_temp.dat");
		//$trace_p("PFO开始解析");
		string PfoFile = "./bpa_temp/OPF_temp.pfo";
        BPAFilesIO::PfoParse toParse(impl->database, impl->caseid, PfoFile);
		int ret = toParse.BasePfoParse();
		zone = toParse.ZoneInfoList;
		line = toParse.LineResultList;
		bus = toParse.BusResultList;
		trans = toParse.TranResultList;
		return ret;
	}
	int BPA_OPF_Analysis::BPA_OPF_Adjust(
		BPA::BPAFilesIO::ZoneInfoVector& zone,
		BPA::BPAFilesIO::LineResultVector& line,
		BPA::BPAFilesIO::BusResultVector& bus,
		BPA::BPAFilesIO::TranResultVector& trans,
		OPF::OPF_DIFF& opf_diff)
	{	
		int ret = 0;
		string OpenFileName = "./bpa_temp/PowerFlow_Adjust.dat";
		//string FileName = "./powerflow_adjust_temp/dat_temp.dat";
		string PfoFile = "./bpa_temp/OPF_temp.pfo";
		//BPAAnalysis(FileName.c_str(), impl->database);

        PowerFlowAutoAdjustment toadjustment(impl->database, impl->caseid);
		bool PfoExist = false;
		PfoExist = toadjustment.ReadBpaPfo(PfoFile.c_str());
		if (PfoExist == false)
		{
			toadjustment.Adjustment(); 
			BPA::BPAFilesIO::Db2Dat dd;
			dd.DataBaseWriteToBpa(impl->database, OpenFileName.c_str(), impl->caseid, true);
			impl->ExecutePF("PowerFlow_Adjust.dat");
			PfoExist = toadjustment.ReadBpaPfo("./bpa_temp/PowerFlow_Adjust.pfo");
		}
		if (PfoExist==true)
		{
			toadjustment.ChangeBack(OpenFileName.c_str());
			BPA::BPAFilesIO::Db2Dat dd;
			dd.DataBaseWriteToBpa(impl->database, OpenFileName.c_str(), impl->caseid,true);
			ret = 1;
			opf_diff.OverBusStart = bus.size();
			opf_diff.OverLineStart = line.size();
			opf_diff.OverTranStart = trans.size();
			impl->ExecutePF("PowerFlow_Adjust.dat");
			BPAFilesIO::PfoParse toParse(impl->database, impl->caseid, "./bpa_temp/PowerFlow_Adjust.pfo");
			if (toParse.BasePfoParse() != 2)
			{
				ret = 0;
			}
			zone = toParse.ZoneInfoList;
			line = toParse.LineResultList;
			bus = toParse.BusResultList;
			trans = toParse.TranResultList;
			opf_diff.OverBusEnd = bus.size();
			opf_diff.OverLineEnd = line.size();
			opf_diff.OverTranEnd = trans.size();
		}
		return ret;
	}
	
    int BPA_OPF_Analysis::BPA_OPF_Minpower()
	{
        /*BPA::BPAFilesIO::Db2Dat w;
		w.DataBaseWriteToBpa(impl->database, "Tmp.dat", impl->caseid);*/
		//w.DataBaseWriteToBpacz(Database, CaseID);

        BPAFilesIO::DatParse datParser;
        datParser.Parsing("./bpa_temp/OPF_temp.dat");//解析函数
		//数据拼接准备工作，重新解析和写入数据库

        datParser.TrimBpaDat1();				//处理函数集合（含功率按指定机制转换）
		//data->DividBusAndLine();
        datParser.TrimBpaDat2();				//处理函数集合（含功率按指定机制转换）
        datParser.GetZoneProvinceID(impl->database);

        datParser.QinDatWriteBack();		//覃老师需要的格式
		//此处执行覃老师的最小化潮流
        ToExecuteMinPf ExeMinPf(impl->database, impl->caseid);
		ExeMinPf.ExecuteMinPf();
        MinPowerFlow minpf(impl->database, impl->caseid);				//残差分析
		minpf.MinPowerFlowResOrder();

        MinPowerInZone qinminpf(impl->database, impl->caseid);		//潮流结果分区统计
		qinminpf.ReleaseMinPfVector();
		qinminpf.MinPowerInZoneAchieve();
		return STS_SUCCEED;
	}

}